﻿
#region ModuleSetup 

$ErrorActionPreference = "SilentlyContinue"
# code to prevent the ntfs.dll file from locking
Get-ChildItem $env:TEMP *.die | Remove-Item -Force -ErrorAction 0
$NTFSDLL = "ntfs_{0}.die" -f (Get-Random)
copy $psScriptRoot\ntfs.dll $env:Temp\$NTFSDLL
[System.Reflection.Assembly]::LoadFile("$env:Temp\$NTFSDLL") | out-null
$ErrorActionPreference = "Continue"

#endregion


#region Block-Script 

function Block-Script
{
    <#
        .Synopsis
            Sets the Alternate Data Stream (ADS) on the file to InternetZone.
            [ZoneTransfer]
            ZoneID=4
            
        .Description
            Sets the Alternate Data Stream on the file to InternetZone.
            [ZoneTransfer]
            ZoneID=4
                        
        .Parameter FileName 
            Path to the file to set the ADS on.
        
        .Example
            Block-Script -FileName C:\Local\MyFile.ps1
            Description
            -----------
            Sets the ADS on 'C:\Local\MyFile.ps1' to Internet Zone.
            
        .Example
            dir c:\temp\myscripts | Block-Script
            Description
            -----------
            Blocks all the files in the path C:\temp\myscripts.
    
        .OUTPUTS
            NTFS.StreamInfo
            
        .INPUTS
            System.String
            
        .Link
            Set-AlternateDataStream
            Unblock-Script
        
        .Notes
            NAME:      Block-Script
            AUTHOR:    bsonposh
            Website:   http://www.bsonposh.com
            Version:   1
            #Requires -Version 2.0
    #>
    
    [Cmdletbinding(SupportsShouldProcess=$True)]
    Param(
        [alias("FullName")]
        [parameter(mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$FileName
    )
    Begin 
    {
        $Name = 'Zone.Identifier'
        $String  = "[ZoneTransfer]`nZoneID=4" 
    }
    Process 
    {
            if(Test-Path $FileName)
            {
                if($PSCmdlet.ShouldProcess($FileName,"Using Set-AlternateDataStream to Block"))
                {
                    Set-AlternateDataStream -FileName $FileName -Name $Name -Text $String
                }
            }
            else
            {
                Write-Host "`$FilePath [$FilePath] not provide or File not Found"
            }
    }
}
    
#endregion 


#region Get-AlternateDataStream 

function Get-AlternateDataStream
{
        
    <#
        .Synopsis 
            Gets Alternate Data Stream from the file passed.
            
        .Description
            Gets Alternate Data Stream from the file passed.
            
        .Parameter FileName
            File to get the Alternate Data Stream from (aliased to FullName for piping.)
            
        .Example
            Get-AlternameDataStream -Filename C:\temp\myfile.ps1
            Description
            -----------
            Gets the ADS from the file C:\temp\myfile.ps1
    
        .Example
            dir c:\temp\myscripts | Get-AlternameDataStream 
            Description
            -----------
            Gets the ADS from each file in the pipeline.
    
        .OUTPUTS
            NTFS.StreamInfo
            
        .INPUTS
            System.String
            
        .Link
            Set-AlternateDataStream
        
        .Notes
            NAME:      Get-AlternameDataStream
            AUTHOR:    bsonposh
            Website:   http://www.bsonposh.com
            Version:   1
            #Requires -Version 2.0
    #>
   
    [Cmdletbinding()]
    Param(
        [alias("FullName")]
        [parameter(mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$FileName
    )
    
    Process 
    {
        Write-Verbose " [Get-AlternateDataStream] :: Begin Process"
        Write-Verbose " [Get-AlternateDataStream] :: Processing $FileName"
        if(Test-Path $FileName)
        {
            Write-Verbose " [Get-AlternateDataStream] :: $FileName found. Getting ADS"
            $ADSObject = New-Object NTFS.FileStreams($FileName)
            if($ADSObject)
            {
                Write-Verbose " [Get-AlternateDataStream] :: Found ADS"
                foreach($ADS in $ADSObject)
                {
                    Write-Verbose " [Get-AlternateDataStream] :: Getting ADS info for [$($ADS.Name)]"
                    # Get Stream Text
                    $stream = $ADSObject.Item($ADS.Name).Open()
                    $streamReader = new-object System.IO.streamreader($stream)
                    $Text = $streamReader.ReadToEnd()
                    $stream.Close() 
                    $streamReader.Close()
                    
                    $MyADSObject = $ADS | Add-Member -Name FileName -Value $FileName -MemberType NoteProperty -PassThru
                    $MyADSObject = $MyADSObject | Add-Member -Name Data -Value $Text -MemberType NoteProperty -PassThru
                    $MyADSObject
                }
            }
            else            {
                Write-Verbose " [Get-AlternateDataStream] :: No ADS Found"
            }
        }
        else
        {
            Write-Host "`$FilePath [$FilePath] not provide or File not Found"
        }
        
        Write-Verbose " [Get-AlternateDataStream] :: End Process"
    }
}
    
#endregion 


#region New-AlternateDataStream 

function New-AlternateDataStream 
{
    
    <#
        .Synopsis 
            Creates an Alternate data stream and attachs to a file.
            
        .Description
            Creates an Alternate data stream and attachs to a file.
        
        .Parameter FullName
            Name and path of the file you want to set the Alternate Data Stream on.
            
        .Parameter Name
            Name of the Alternate Data Stream
        
        .Parameter Text
            Data to be stored in the Alternate Data Stream
                
        .Example
            New-AlternateDataStream -FullName c:\temp\myfile.ps1 -name 'Zone.Identifier' -text "[ZoneTransfer]`nZoneID=4"
            Description
            -----------
            Creates the following ADS and sets on the file c:\temp\myfile.ps1
            
            [ZoneTransfer]
            ZoneID=4
            
        .OUTPUTS
            NTFS.StreamInfo
            
        .INPUTS
            System.String
            
        .Link
            Get-AlternateDataStream
            Set-AlternateDataStream
            
        .Notes
            NAME:      Block-Script
            AUTHOR:    bsonposh
            Website:   http://www.bsonposh.com
            Version:   1
            #Requires -Version 2.0
    #>
    
    [Cmdletbinding(SupportsShouldProcess=$True)]
    Param(
    
        [parameter(mandatory=$true)]
        [string]$Name,
        
        [parameter(mandatory=$true)]
        [string]$Text,
        
        [alias("FullName")]
        [parameter(mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
        [string]$FileName
        
    )
    Process 
    {
    
        Write-Verbose " [New-AlternateDataStream] :: Begin Process"
        
        if(Test-Path $FileName)
        {
            Write-Verbose " [New-AlternateDataStream] :: $FileName Found"
            Write-Verbose " [New-AlternateDataStream] :: Processing ADS"
            $ADS = New-Object NTFS.FileStreams($FileName)
            if($PSCmdlet.ShouldProcess($FileName,"Creating Alternate Data Stream $Name"))
            {
                Write-Verbose " [New-AlternateDataStream] :: Adding ADS $Name"
                $ADS.Add($Name)
                Write-Verbose " [New-AlternateDataStream] :: Creating Stream for $Name"
                $stream = $ADS.Item($Name).open()                           
                Write-Verbose " [New-AlternateDataStream] :: Setting $Text to $Name"
                $sw = [System.IO.streamwriter]$stream
                $Sw.write($Text)      
                
                Write-Verbose " [New-AlternateDataStream] :: Closing ADS"
                $sw.close()                                                                                            
                            
                $stream.close()
                
                # Returning ADS text
                Write-Verbose " [New-AlternateDataStream] :: Returning ADS Object via Get-AlternateDataStream"
                Get-AlternateDataStream $FileName
            }
        }
        else
        {
            Write-Verbose " [New-AlternateDataStream] :: File not Found"
        }
        
        Write-Verbose " [New-AlternateDataStream] :: End Process"
    
    }
}
    
#endregion 
